package com.chukun.multi.twophase;

import org.omg.CORBA.ObjectHelper;

import java.lang.ref.WeakReference;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author chukun
 *  线程停止的标志
 */
public class TerminationToken {

    // 使用 volatile 修饰，保证在无锁的情况下，该变量的内存可见性
    protected volatile boolean toShutdown = false;

    public final AtomicInteger reservations = new AtomicInteger(0);

    /**
     * 在多个可以停止的线程实例共享一个TerminationToken实例的情况下，该队列用于记录那些共享TerminationToken
     * 实例的可以停止的线程，以便尽可能减少锁的使用的情况下，实现这些线程的停止
     */
    private final Queue<WeakReference<Terminatable>> coordinatedThreads;

    public TerminationToken () {
        coordinatedThreads = new ConcurrentLinkedDeque<>();
    }

    public boolean isToShutdown() {
        return toShutdown;
    }

    protected void setToShutdown(boolean toShutdown) {
        this.toShutdown = toShutdown;
    }

    protected void register(Terminatable thread) {
        coordinatedThreads.add(new WeakReference<>(thread));
    }

    /**
     * 通知TerminationToken实例：共享该实例的所有可以停止的线程中的一个线程停止了，
     * 以便其停止其他未停止的线程
     * @param thread 已经停止的线程
     */
    protected void notifyThreadTermination(Terminatable thread) {
        WeakReference<Terminatable> wrThread;
        Terminatable otherThread;
        while (null != (wrThread = coordinatedThreads.poll())) {
            otherThread = wrThread.get();
            if (null != otherThread && otherThread != thread) {
                otherThread.terminate();
            }
        }
    }
}
